package org.atlantis.grosbeak.castor.defaults;

import java.lang.reflect.Field;
import java.lang.reflect.Type;

import org.atlantis.grosbeak.castor.Castor;
import org.atlantis.grosbeak.castor.FailToCastException;
import org.atlantis.grosbeak.lang.Exceptions;
import org.atlantis.grosbeak.lang.Mirror;

@SuppressWarnings("unchecked")
public class EnumToNumber implements Castor<Enum, Number> {

	public Type getFrom() {
		return Enum.class;
	}

	public Type getTo() {
		return Number.class;
	}

	public Number obverseCast(Enum src, Class<?> toType)
			throws FailToCastException {
		Mirror<?> mir = Mirror.me(Integer.class);
		Integer re = src.ordinal();
		if (mir.canCastToDirectly(toType))
			return re;
		return (Number) Mirror.me(toType).fruit(re.toString());
	}

	public Enum reverseCast(Number src, Class<?> toType)
			throws FailToCastException {
		try {
			for (Field field : toType.getFields()) {
				if (field.getType() == toType) {
					Enum en = (Enum) field.get(null);
					if (en.ordinal() == src.intValue())
						return en;
				}
			}
			throw Exceptions.makeThrow(FailToCastException.class,
					"Unable to find enum value '%s' by int value '%d'.", toType
							.getName(), src.intValue());
		} catch (Exception e) {
			throw Exceptions.wrapThrow(FailToCastException.class, e);
		}
	}
}
